package com.unience.ec2.eclipse;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.ITreeViewerListener;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ArmEvent;
import org.eclipse.swt.events.ArmListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Decorations;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

import com.unience.ec2.eclipse.config.Config;
import com.unience.ec2.eclipse.config.UtilSWT;
import com.unience.ec2.eclipse.view.ImageViewPart;
import com.unience.ec2.eclipse.view.InstanceViewPart;
import com.unience.ec2.eclipse.view.SecurityGroupViewPart;
import com.unience.ec2.test.LaunchEc2InstanceTest;
import com.xerox.amazonws.ec2.EC2Exception;
import com.xerox.amazonws.ec2.GroupDescription;
import com.xerox.amazonws.ec2.ImageDescription;
import com.xerox.amazonws.ec2.ReservationDescription;
import com.xerox.amazonws.ec2.ReservationDescription.Instance;


public class NavigationView extends ViewPart {
	
	private static Log log = LogFactory.getLog(NavigationView.class);
	public static final String ID = "com.unience.ec2.eclipse.navigationView";
	private TreeViewer viewer;
	
	private OpenViewAction openViewAction;
	
	
	 
	
	class TreeEc2Image extends  TreeObject{
		private Ec2ModelNode parent;
		private ImageDescription instance;
		public void setParent(Ec2ModelNode parent) {
			this.parent = parent;
		}
		public Ec2ModelNode getParent() {
			return parent;
		}
		
		public TreeEc2Image(String name) {
			super(name);
		}
		public TreeEc2Image(ImageDescription instance){
			super(instance.getImageId());
			this.instance = instance;
			
		}
		public ImageDescription getInstance() {
			return instance;
		}
		public void setInstance(ImageDescription instance) {
			this.instance = instance;
		}
		
		public String toString() {
			return instance.getImageId();
		}
		
	}
	class TreeEc2Instance extends  TreeObject{
		private Ec2ModelNode parent;
		private Instance instance;
		public void setParent(Ec2ModelNode parent) {
			this.parent = parent;
		}
		public Ec2ModelNode getParent() {
			return parent;
		}
		
		public TreeEc2Instance(String name) {
			super(name);
		}
		public TreeEc2Instance(Instance instance){
			super(instance.getInstanceId());
			this.instance = instance;
			
		}
		public Instance getInstance() {
			return instance;
		}
		public void setInstance(Instance instance) {
			this.instance = instance;
		}
		
		public String toString() {
			return instance.getInstanceId();
		}
		
	}
	
	
	class TreeEc2SecurityGroup extends  TreeObject{
		private Ec2ModelNode parent;
		private GroupDescription group;
		public void setParent(Ec2ModelNode parent) {
			this.parent = parent;
		}
		public Ec2ModelNode getParent() {
			return parent;
		}
		
		public TreeEc2SecurityGroup(String name) {
			super(name);
		}
		public TreeEc2SecurityGroup(GroupDescription group){
			super(group.getName());
			this.group = group;
			
		}
		public GroupDescription getGroup() {
			return group;
		}
		public void setGroup(GroupDescription group) {
			this.group = group;
		}
		
		public String toString() {
			return group.getName();
		}
		
	}
	class TreeObject {
		private String name;
		private Ec2ModelNode parent;
		
		public TreeObject(String name) {
			this.name = name;
		}
		public String getName() {
			return name;
		}
		public void setParent(Ec2ModelNode parent) {
			this.parent = parent;
		}
		public Ec2ModelNode getParent() {
			return parent;
		}
		public String toString() {
			return getName();
		}
	}
	
	class Ec2ModelNode {
		private ArrayList children;
		private String name;
		private Ec2Model parent;
		
		public Ec2ModelNode(String name) {
			this.name = name;
			children = new ArrayList();
		}
		public void addChild(TreeObject child) {
			children.add(child);
			child.setParent(this);
		}
		public void removeChild(TreeObject child) {
			children.remove(child);
			child.setParent(null);
		}
		public TreeObject[] getChildren() {
			return (TreeObject[]) children.toArray(new TreeObject[children.size()]);
		}
		public boolean hasChildren() {
			return children.size()>0;
		}
		
		public void setParent(Ec2Model parent) {
			this.parent = parent;
		}
		public Ec2Model getParent() {
			return parent;
		}
	}
	
	class Ec2Model extends TreeObject {
		private ArrayList children;
		public Ec2Model(String name) {
			super(name);
			children = new ArrayList();
		}
		public void addChild(Ec2ModelNode child) {
			children.add(child);
			child.setParent(this);
		}
		public void removeChild(TreeObject child) {
			children.remove(child);
			child.setParent(null);
		}
		public TreeObject[] getChildren() {
			return (TreeObject[]) children.toArray(new TreeObject[children.size()]);
		}
		public boolean hasChildren() {
			return children.size()>0;
		}
	}
		

	class  TreeDoubleClickListerner    implements IDoubleClickListener{

		private final IWorkbenchWindow window;
		public TreeDoubleClickListerner(final IWorkbenchWindow window){
			this.window = window;
		}
	
		public void doubleClick(DoubleClickEvent event) {
			log.info("DoubleClicked Tree");
			Object obj = event.getSource();
			
			log.info("object doubleClicked " + obj.getClass().getName());
			
			if ( obj  instanceof TreeViewer) {
				TreeViewer tree = (TreeViewer) obj;
			
				Object objectSelected = ((ITreeSelection)event.getSelection()).getFirstElement();
				log.info("object doubleClicked " + objectSelected.getClass().getName());
				
				if ( objectSelected instanceof TreeEc2SecurityGroup) {
					TreeEc2SecurityGroup securityGroupElem = (TreeEc2SecurityGroup) objectSelected;
					GroupDescription groupDesc = securityGroupElem.getGroup();
					
					Config.getInstance().setLastSelection(groupDesc);
					
					if (openViewAction == null){
						
						openViewAction = new OpenViewAction(window, "Open Another Ec2 GroupDescription View",  SecurityGroupViewPart.ID_VIEW);
						
					}
					openViewAction.run();
				}
				
				if ( objectSelected instanceof TreeEc2Instance) {
					TreeEc2Instance ec2Instane = (TreeEc2Instance) objectSelected;
					Instance instance = ec2Instane.getInstance();
					
					Config.getInstance().setLastSelection(instance);
					
					if (openViewAction == null){						
						openViewAction = new OpenViewAction(window, "Open Another Ec2 Instance View",InstanceViewPart.ID_VIEW);
					}
					openViewAction.run();
				}
				
				
				
				if ( objectSelected instanceof TreeEc2Image) {
					TreeEc2Image treeObject = (TreeEc2Image) objectSelected;					
					
					Config.getInstance().setLastSelection(treeObject.getInstance());
					
					if (openViewAction == null){						
						openViewAction = new OpenViewAction(window, "Open Another Ec2 Instance View",ImageViewPart.ID_VIEW);
					}
					openViewAction.run();
				}
				
			}
			
			
		}
		
		
	}
	class ViewContentProvider implements IStructuredContentProvider, 
										   ITreeContentProvider {

        public void inputChanged(Viewer v, Object oldInput, Object newInput) {
		}
        
		public void dispose() {
		}
        
		public Object[] getElements(Object parent) {
			return getChildren(parent);
		}
        
		public Object getParent(Object child) {
			if (child instanceof TreeObject) {
				return ((TreeObject)child).getParent();
			}
			return null;
		}
        
		public Object[] getChildren(Object parent) {
			if (parent instanceof Ec2ModelNode) {
				return ((Ec2ModelNode)parent).getChildren();
			}
			return new Object[0];
		}

        public boolean hasChildren(Object parent) {
			if (parent instanceof Ec2ModelNode)
				return ((Ec2ModelNode)parent).hasChildren();
			return false;
		}
	}
	
	class ViewLabelProvider extends LabelProvider {

		public String getText(Object obj) {
			return obj.toString();
		}
		public Image getImage(Object obj) {
			String imageKey = ISharedImages.IMG_OBJ_ELEMENT;
			if (obj instanceof Ec2ModelNode)
			   imageKey = ISharedImages.IMG_OBJ_FOLDER;
			return PlatformUI.getWorkbench().getSharedImages().getImage(imageKey);
		}
	}

    /**
     * We will set up a dummy model to initialize tree heararchy. In real
     * code, you will connect to a real model and expose its hierarchy.
     */
    private Ec2Model createDummyModel() {
    	
    	Config config = Config.getInstance();
    	LaunchEc2InstanceTest myec2 = config.getEc2Instance();
    	
    	List<ImageDescription> myImages = myec2.getMyImages();
    	
    	Ec2ModelNode p0 = new Ec2ModelNode("MyImages");
    	
    	if (myImages != null){
	    	for (ImageDescription myImage:myImages){
	    		TreeEc2Image to1 = new TreeEc2Image(myImage);
	    		 
	    		 p0.addChild(to1);
	    	}
    	}
    	
    	List<GroupDescription> securityCroups = myec2.getSecurityGroups();
    	
    	Ec2ModelNode p1 = new Ec2ModelNode("SecurityGroups");
    	for (GroupDescription group:securityCroups){
    		TreeEc2SecurityGroup to1 = new TreeEc2SecurityGroup(group);
    		 p1.addChild(to1);
    	}
    	
    	Ec2ModelNode p2 = new Ec2ModelNode("Ec2 Instances");
    	List<Instance> instances = myec2.checkInstances();
    	for (Instance instance:instances){
    		TreeEc2Instance to = new TreeEc2Instance(instance);
   		    p2.addChild(to);
   	    }
    	

        Ec2Model root = new Ec2Model("MyEc2");
        root.addChild(p0);
        root.addChild(p1);
        root.addChild(p2);
        return root;
    }

	/**
     * This is a callback that will allow us to create the viewer and initialize
     * it.
     */
	public void createPartControl(Composite parent) {
		viewer = new TreeViewer(parent, SWT.SIMPLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
		
		viewer.setContentProvider(new ViewContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());
		
		Ec2Model model = createDummyModel();
		//Config.getInstance().setTreeModel(treeModel);
		viewer.setInput(model);
		viewer.addDoubleClickListener(new TreeDoubleClickListerner(this.getSite().getWorkbenchWindow()));
		viewer.getTree().setMenu(createPopUpMenu(parent.getShell()));
		
	}
	
	
	private Menu createPopUpMenu(final Decorations parent){
		 final Menu menu =   new Menu(parent, SWT.POP_UP);
		/* MenuItem item = new MenuItem(menu, SWT.PUSH);
		 item.setText("Start Ec2 Instance");
		 
		 MenuItem item2 = new MenuItem(menu, SWT.PUSH);
		 item2.setText("Stop Ec2 Instance");
		 */
		 menu.addListener (SWT.Show, new Listener () {
				public void handleEvent (Event event) {
					MenuItem [] menuItems = menu.getItems ();
					TreeItem [] treeItems = viewer.getTree().getSelection ();
					
					
					for (int i=0; i<menuItems.length; i++) {
						menuItems [i].dispose ();
					}


					for (int i=0; i<treeItems.length; i++) {
						TreeItem treeItem = treeItems[i];
						Object data = treeItem.getData();
						
						if (data  instanceof TreeEc2Image) {
							TreeEc2Image ec2image = (TreeEc2Image) data ;
							 
							
							 MenuItem item = new MenuItem(menu, SWT.PUSH);
							 item.setText("Start Ec2 Instance");
							
							 
							 item.addSelectionListener(new MenuItemSelectionAdapter(ec2image.getInstance())); 
						}
						if (data  instanceof TreeEc2SecurityGroup) {
							TreeEc2SecurityGroup ec2secGroup = (TreeEc2SecurityGroup) data ;
							//no menu options....
						}
						
						if (data  instanceof TreeEc2Instance) {
							TreeEc2Instance ec2secGroup = (TreeEc2Instance) data ;
							 MenuItem item = new MenuItem(menu, SWT.PUSH);
							 item.setText("Stop Ec2 Instance");
							 
							 item.addSelectionListener(new MenuItemSelectionAdapter(ec2secGroup.getInstance()));

						}
						
						
						log.info("Tipo de dato : " + data.getClass());
					}					
					
				}
			});

		
		 return menu;
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		viewer.getControl().setFocus();
	}
	
	
	
	class MenuItemSelectionAdapter extends SelectionAdapter{
		private Object selectedObject;
		public MenuItemSelectionAdapter (Object obj){
			super();
			selectedObject = obj;
		}
		
		 public void widgetSelected(SelectionEvent e) {
			
			  if (selectedObject instanceof GroupDescription) {
				  GroupDescription ec2secGroup = (GroupDescription) selectedObject;
				  log.info("Security Group Selected: " + ec2secGroup.getName());
			 	
			 }
			  
			  if (selectedObject instanceof ImageDescription) {
				  ImageDescription imageDesc = (ImageDescription) selectedObject;				  
					
				  
				  boolean bStart = MessageDialog.openQuestion(UtilSWT.getShell(), "Start New Ec2 Instance", "You are about to init a new Ec2 instance:" + imageDesc.getImageId());
				 
				 
				  if (bStart){
					  log.info("Starting ec2Instace of ami: " + imageDesc.getImageId());
					  List<String> groupSet = new  ArrayList<String>();
				      String userData ="";
				      String keyName = "gsg-keypair";
					  try {
						Config.getInstance().getEc2Instance().createInstance(imageDesc.getImageId(), groupSet, userData, keyName);
					} catch (EC2Exception e1) {
						MessageDialog.openError(UtilSWT.getShell(), "Error Starting Ec2 Instance", e1.getMessage());
						log.error(e1.getMessage());
					}
				  }
			 	
			 }
			  
			  
			  if (selectedObject instanceof Instance) {
				Instance instance = (Instance) selectedObject;
				
				 boolean bStop = MessageDialog.openQuestion(UtilSWT.getShell(), "Stop New Ec2 Instance", "You are about to Stop the Ec2 instance: " + instance.getInstanceId());
				 
				 
				  if (bStop){
					  log.info("Starting ec2Instace of ami: " + instance.getImageId());
					  List<String> groupSet = new  ArrayList<String>();
				      String userData ="";
				      String keyName = "gsg-keypair";
					  try {
						List<String> instanceIds = new ArrayList<String>();
						instanceIds.add(instance.getInstanceId());
						Config.getInstance().getEc2Instance().getEc2().terminateInstances(instanceIds);
					} catch (EC2Exception e1) {
						MessageDialog.openError(UtilSWT.getShell(), "Error Starting Ec2 Instance", e1.getMessage());
						log.error(e1.getMessage());
					}
				  }
				
				
			}
			    
	          
	          
	        }
		
		
	}
}